package com.zijidelu.luframework.utils.spring.beans.register;


import com.zijidelu.luframework.utils.CastUtil;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.UUID;

/**
 * SpringSimpleBeanUtil 是一个全局工具类，用于操作 Spring 容器：
 * - 对非 Spring 管理对象进行依赖注入
 * - 初始化对象生命周期（@PostConstruct、AOP 等）
 * - 动态注册 Bean 到 Spring 容器
 * - 提供获取 Bean 的便捷方法
 * <p>
 * 实现了 ApplicationContextAware 以获取容器引用，
 * 也实现了 DynamicBeanRegister 接口用于动态注册 Bean。
 *
 * @author ZIJIDELU
 * @datetime 2025/10/13 23:04
 */
@Component
public final class SpringSimpleBeanUtil implements ApplicationContextAware, DynamicBeanRegister {

    /**
     * 全局单例实例
     */
    private static volatile SpringSimpleBeanUtil INSTANCE;

    /**
     * Spring 容器上下文
     */
    private static ApplicationContext APPLICATION_CONTEXT;

    /**
     * 可注入 Bean 的工厂（支持 autowire）
     */
    private static AutowireCapableBeanFactory AUTOWIRE_CAPABLE_BEAN_FACTORY;

    /**
     * Spring 默认可注册 Bean 的工厂
     */
    private static DefaultListableBeanFactory BEAN_FACTORY;

    /**
     * Spring 启动时自动注入 ApplicationContext
     * 并初始化静态工厂和 INSTANCE
     */
    @Override
    public void setApplicationContext(@NonNull ApplicationContext applicationContext) throws BeansException {
        APPLICATION_CONTEXT = applicationContext;
        AUTOWIRE_CAPABLE_BEAN_FACTORY = applicationContext.getAutowireCapableBeanFactory();
        BEAN_FACTORY = (DefaultListableBeanFactory) AUTOWIRE_CAPABLE_BEAN_FACTORY;
        INSTANCE = this;
    }

    /* ========================= 工具方法 ========================= */

    /**
     * 对非 Spring 管理的对象进行依赖注入
     * 不注册到容器，也不触发生命周期
     *
     * @param instance 要注入的对象
     * @param <T>      类型
     * @return 注入完成的对象
     */
    public static <T> T autowire(T instance) {
        Objects.requireNonNull(instance, "instance must not be null");
        AUTOWIRE_CAPABLE_BEAN_FACTORY.autowireBean(instance);
        return instance;
    }

    /**
     * 对非 Spring 管理的对象进行依赖注入并初始化完整生命周期
     * 包含 @PostConstruct 和 AOP 代理等
     *
     * @param instance 要初始化的对象
     * @param <T>      类型
     * @return 初始化完成的对象
     */
    public static <T> T initialize(T instance) {
        Objects.requireNonNull(instance, "instance must not be null");
        String beanName = instance.getClass().getName() + "#" + UUID.randomUUID();
        return (T) AUTOWIRE_CAPABLE_BEAN_FACTORY.initializeBean(instance, beanName);
    }

    /**
     * 将指定类注册为 Spring 单例 Bean
     * 如果 Bean 已存在则直接返回已有 Bean
     *
     * @param beanName Bean 名称
     * @param clazz    Bean 类型
     * @param <T>      类型
     * @return 注册后的 Bean 实例
     */
    public static <T> T registerSingleton(String beanName, Class<T> clazz) {
        Objects.requireNonNull(beanName, "beanName must not be null");
        Objects.requireNonNull(clazz, "clazz must not be null");
        if (BEAN_FACTORY.containsBeanDefinition(beanName) || APPLICATION_CONTEXT.containsBean(beanName)) {
            return APPLICATION_CONTEXT.getBean(beanName, clazz);
        }
        BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(clazz);
        BEAN_FACTORY.registerBeanDefinition(beanName, builder.getBeanDefinition());
        return APPLICATION_CONTEXT.getBean(beanName, clazz);
    }

    /**
     * 将已有实例注册为 Spring 单例 Bean
     *
     * @param beanName Bean 名称
     * @param instance Bean 实例
     * @param <T>      类型
     * @return 注册后的 Bean
     */
    public static <T> T registerSingleton(String beanName, T instance) {
        Objects.requireNonNull(beanName, "beanName must not be null");
        Objects.requireNonNull(instance, "instance must not be null");
        BEAN_FACTORY.registerSingleton(beanName, instance);
        return instance;
    }

    /* ========================= 获取 Bean ========================= */

    /**
     * 获取指定类型的 Bean
     */
    public static <T> T getBean(Class<T> clazz) {
        return APPLICATION_CONTEXT.getBean(clazz);
    }

    /**
     * 获取指定名称和类型的 Bean
     */
    public static <T> T getBean(String name, Class<T> clazz) {
        return APPLICATION_CONTEXT.getBean(name, clazz);
    }

    /**
     * 获取 ApplicationContext
     */
    public static ApplicationContext getApplicationContext() {
        return APPLICATION_CONTEXT;
    }

    /* ========================= DynamicBeanRegister 接口 ========================= */

    /**
     * 注册 Bean
     */
    @Override
    public void registerBean(String beanName, Class<?> beanClass) {
        registerSingleton(beanName, beanClass);
    }

    /**
     * 检查 Bean 是否存在
     */
    @Override
    public boolean containsBean(String beanName) {
        return BEAN_FACTORY.containsBeanDefinition(beanName) || APPLICATION_CONTEXT.containsBean(beanName);
    }

    /**
     * 获取 Bean，如果不存在返回 Optional.empty()
     */
    @Override
    public Optional<?> getBeanIfExists(String beanName) {
        try {
            return APPLICATION_CONTEXT.containsBean(beanName) ?
                    Optional.of(APPLICATION_CONTEXT.getBean(beanName)) : Optional.empty();
        } catch (Exception e) {
            return Optional.empty();
        }
    }

    /**
     * 获取 Bean，如果不存在返回 Optional.empty()
     */
    @Override
    public <T> Optional<T> getBeanIfExists(String beanName, Class<T> beanType) {
        try {
            return APPLICATION_CONTEXT.containsBean(beanName) ?
                    Optional.of(APPLICATION_CONTEXT.getBean(beanName, beanType)) : Optional.empty();
        } catch (Exception e) {
            return Optional.empty();
        }
    }

    /**
     * 获取 Bean，如果不存在返回 Optional.empty()
     */
    @Override
    public <T> Optional<T> getBeanIfExists(Class<T> beanType) {
        try {
            return Optional.ofNullable(APPLICATION_CONTEXT.getBean(beanType));
        } catch (NoSuchBeanDefinitionException e) {
            return Optional.empty();
        }
    }

    /**
     * 获取指定类型的所有 Bean
     */
    @Override
    public <T> Map<String, T> getBeansOfType(Class<?> beanType) {
        return CastUtil.cast(APPLICATION_CONTEXT.getBeansOfType(beanType));
    }

    /**
     * 获取全局 DynamicBeanRegister 实例
     */
    public static SpringSimpleBeanUtil getInstance() {
        return INSTANCE;
    }
}
